﻿#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    init();

    // 当父对象(this)销毁时自动销毁该模型
    model_b = new QSqlTableModel(this);
    model_b->setTable("basic_inf");
    // 从数据库加载basic_inf数据
    model_b->select();
    model_d = new QSqlTableModel(this);
    model_d->setTable("details_inf");
    // 从数据库加载details_inf文件
    model_d->select();
    ui->basicTabeView->setModel(model_b);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::onTimeOut()
{
    QTime nowTime = QTime::currentTime();
    ui->timeEdit->setTime(nowTime);
}

void Widget::init()
{
    QString applicationDirPath = QCoreApplication::applicationDirPath();
    QString ctImgPath = applicationDirPath + "/Tumor.jpg";
    qDebug() << ctImgPath;
    // ​局限性：Latin-1仅支持ASCII字符（0-255），如果路径包含中文或其他非ASCII字符，会转换为乱码或空数据，导致读取失败。
    // 提取QByteArray内部的const char*指针，供imread()使用。
    Mat ctImg = cv::imread(ctImgPath.toLatin1().data());
    // 图像从 BGR 颜色空间转换为 RGB 颜色空间。
    cvtColor(ctImg, ctImg, COLOR_BGR2RGB);
    myCtImg = ctImg;
    myCtQImage = QImage((const unsigned char*)(ctImg.data), ctImg.cols, ctImg.rows, QImage::Format_RGB888);
    ctImgShow();

    QDate date = QDate::currentDate();
    int year = date.year();
    ui->yearLcdNumber->display(year);
    int month = date.month();
    ui->mouthLcdNumber_2->display(month);
    int day = date.day();
    ui->dayLcdNumber_3->display(day);

    myTimer = new QTimer();
    myTimer->setInterval(1000);
    myTimer->start();
    connect(myTimer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
}

void Widget::ctImgShow()
{
    // 参数1：目标大小(这里是label的尺寸)
    // 参数2：缩放模式Qt::KeepAspectRatio(保持宽高比)
    // 将缩放后的QImage转换为QPixmap
    // 显示
    ui->label_3->setPixmap(QPixmap::fromImage(myCtQImage.scaled(ui->label_3->size(), Qt::KeepAspectRatio)));
}

void Widget::onTableSelectChange(int row)
{
    int r = 1;
    if(row != 0) {
        r = ui->basicTabeView->currentIndex().row();
    }
    QModelIndex index;

    // 姓名
    index = model_b->index(r, 1);
    ui->nameLB->setText(model_b->data(index).toString());
    // 性别
    index = model_b->index(r, 2);
    QString sex = model_b->data(index).toString();
    if(sex.compare("男") == 0) {
        ui->maleRB->setChecked(true);
    } else {
        ui->femaleRB->setChecked(true);
    }
    // 民族
    index = model_b->index(r, 3);
    QString minzu = model_b->data(index).toString();
    ui->ethComboBox->setCurrentText("minzu");
    // 年龄
    index = model_b->index(r, 4);
    int bir = model_b->data(index).toDate().year();
    QDate date;
    int now = date.currentDate().year();
    ui->agesSpinBox->setValue(now - bir);
    // 身份证号
    index = model_b->index(r, 0);
    QString ssn = model_b->data(index).toString();
    ui->ssnLineEdit->setText(ssn);

    showUserPhoto();
}

void Widget::showUserPhoto()
{
    QPixmap photo;
    QModelIndex index;

    for(int i = 0; i < model_d->rowCount(); i++) {
        index = model_d->index(i, 0);
        QString current_name = model_d->data(index).toString();

        if(current_name.compare(ui->nameLB->text()) == 0) {
            index = model_d->index(i, 2);
            break;
        }
    }
    QByteArray data = model_d->data(index).toByteArray();
    QByteArray image = QByteArray::fromBase64(data);
    photo.loadFromData(image, "JPG");
    ui->photoLB->setPixmap(photo);
}

void Widget::ctImgRead()
{
    QString ctImgName = QFileDialog::getOpenFileName(
                this,
                u8"载入ct相片",
                ".",
                "Imag File(*.png *.jpg *.jpeg *.bmp)"
                );
    if(ctImgName.isEmpty()) {
        return;
    }
    // opencv读取const char*类型
    Mat ctImg = imread(ctImgName.toLatin1().data());
    Mat ctRGBImg, ctGrayImg;
    // 颜色空间转换
    cvtColor(ctImg, ctRGBImg, COLOR_BGR2RGB);
    cvtColor(ctRGBImg, ctGrayImg, COLOR_RGBA2GRAY);
    // 存储
    myctRGBImg = ctRGBImg;
    myctGrayImg = ctGrayImg;

    // 将 OpenCV 的 cv::Mat 图像数据转换为 Qt 的 QImage 对象
    myCtQImage = QImage(
                (const unsigned char*)(ctRGBImg.data),
                ctRGBImg.cols,
                ctRGBImg.rows,
                QImage::Format_RGB888
                );

    ctImgShow();
}

void Widget::ctImgProc()
{
    QTime time;
    time.start();
    ui->progressBar->setValue(19);
    while(time.elapsed() < 2000) {
        QCoreApplication::processEvents();
    }
    ctImgHoughCircles();
    while(time.elapsed() < 2000) {
        QCoreApplication::processEvents();
    }
    ui->progressBar->setValue(ui->progressBar->value() + 20);
    ctImgShow();
    while(time.elapsed() < 2000) {
        QCoreApplication::processEvents();
    }
    ui->progressBar->setValue(ui->progressBar->maximum());
    QMessageBox::information(this, u8"完毕", u8"子宫内壁见椭球型阴影，疑似子宫瘤");
}

void Widget::ctImgSave()
{
    QFile image("Tumer_proced.jpg");
    if(!image.open(QIODevice::ReadWrite)) {
        return;
    }

    // 2. 准备图像数据缓冲区
    QByteArray array;   // 创建字节数组用于临时存储图像数据
    QBuffer buf(&array);    // 创建缓冲区关联到字节数组
    buf.open(QIODevice::WriteOnly);

    // 3. 图像保存到缓冲区
    myCtQImage.save(&buf, "JPG");

    // 4. 缓冲区写入文件
    image.write(array);
}

void Widget::ctImgHoughCircles()
{
    Mat ctGrayImg = myctGrayImg;
    Mat ctBGRImg;

    // 灰度图像转彩色(BGR opencv默认格式)
    cvtColor(ctGrayImg, ctBGRImg, COLOR_GRAY2BGR);
//    InputArray src,     // 输入图像
//    OutputArray dst,    // 输出图像
//    Size ksize,         // 高斯核大小
//    double sigmaX,      // X方向标准差
//    double sigmaY = 0,  // Y方向标准差（默认=sigmaX）
    GaussianBlur(ctGrayImg, ctGrayImg, Size(9, 9), 2, 2);

    // 保存检测结果（每个圆用Vec3f表示：x,y,radius）
    vector<Vec3f> h_circles;

    // 参数说明：
    // HOUGH_GRADIENT - 检测方法
    // 2 - 累加器分辨率与图像的比例因子
    // ctGrayImg.rows/8 - 最小圆心间距
    // 200 - Canny边缘检测高阈值
    // 100 - 累加器阈值（值越小检测到的圆越多）
    HoughCircles(ctGrayImg, h_circles, HOUGH_GRADIENT, 2, ctGrayImg.rows/8, 200, 100);

    int processValue = 45;
    ui->progressBar->setValue(processValue);
    QTime time;
    // 添加2秒延迟（模拟处理时间）
    while(time.elapsed() < 2000) {
        QCoreApplication::processEvents(); // 保持ui进程
    }
    for(int i = 0; i < h_circles.size(); i++) {
        // cvRound取整
        // cv::Point***OpenCV 的基础数据类型，表示 2D 点坐标。
        Point center(cvRound(h_circles[i][0]), cvRound(h_circles[i][1]));
        int radius = cvRound(h_circles[i][2]);

        circle(ctBGRImg, center,radius,Scalar(238,0,238), 3);
        // -1填充整个实心圆
        circle(ctBGRImg, center,3,Scalar(238,0,0), -1);
        processValue += 1;
        ui->progressBar->setValue(processValue);
    }

    myCtImg = ctBGRImg;
    myCtQImage = QImage((const unsigned char*)(myCtImg.data), myCtImg.cols, myCtImg.rows, QImage::Format_RGB888);
}


void Widget::on_pushButton_clicked()
{
    ctImgRead();
    QTime time;
    // 忙碌状态 类似加载中的效果
    ui->progressBar->setMaximum(0);
    while(time.elapsed() < 5000) {
        // 处理其他事件，避免ui冲突
        QCoreApplication::processEvents();
    }
    ui->progressBar->setMaximum(100);
    ui->progressBar->setMinimum(0);

    ctImgProc();
    ui->progressBar->setValue(0);
    ctImgSave();
}


void Widget::on_tabWidget_tabBarClicked(int index)
{
    if(index == 1) {
        QModelIndex index;
        for(int i = 0; i < model_d->rowCount(); i++) {
            index = model_d->index(i, 0);
            QString current_name = model_b->data(index).toString();
            if(current_name.compare(ui->nameLB->text()) == 0) {
                index = model_d->index(i, 1);
                break;
            }
        }

        ui->textEdit->setText(model_d->data(index).toString());
    }
}

